#pragma once

extern "C" {
#    include "lstate.h"
#    include "lua.h"
#    include "lauxlib.h"
#    include "lualib.h"
}

#include "gd.h"

#define IMAGE "Image"

typedef gdImagePtr Image;

class CGDLib
{
public:
	CGDLib(void);
	~CGDLib(void);

	static Image toImage (lua_State *L, int index)
{
  Image *pi = (Image *)lua_touserdata(L, index);
  if (pi == NULL) luaL_typerror(L, index, IMAGE);
  return *pi;
}

static Image checkImage (lua_State *L, int index)
{
  Image *pi, im;
  luaL_checktype(L, index, LUA_TUSERDATA);
  pi = (Image*)luaL_checkudata(L, index, IMAGE);
  if (pi == NULL) luaL_typerror(L, index, IMAGE);
  im = *pi;
  if (!im)
    luaL_error(L, "null Image");
  return im;
}

static Image *pushImage (lua_State *L, Image im)
{
  Image *pi = (Image *)lua_newuserdata(L, sizeof(Image));
  *pi = im;
  luaL_getmetatable(L, IMAGE);
  lua_setmetatable(L, -2);
  return pi;
}


static int Image_new (lua_State *L)
{
  int x = luaL_checkint(L, 1);
  int y = luaL_checkint(L, 2);
  pushImage(L, gdImageCreate(x, y));
  return 1;
}

static int Image_color_allocate (lua_State *L)
{
  Image im = checkImage(L, 1);
  int r = luaL_checkint(L, 2);
  int g = luaL_checkint(L, 3);
  int b = luaL_checkint(L, 4);
  lua_pushnumber(L, gdImageColorAllocate(im, r, g, b));
  return 1;
}

static int Image_line (lua_State *L)
{
  Image im = checkImage(L, 1);
  int x1     = luaL_checkint(L, 2);
  int y1     = luaL_checkint(L, 3);
  int x2     = luaL_checkint(L, 4);
  int y2     = luaL_checkint(L, 5);
  int colour = luaL_checkint(L, 6);
  gdImageLine(im, x1, y1, x2, y2, colour);
  return 0;
}

static int Image_png (lua_State *L)
{
  /* Output the image to the disk file in PNG format. */
  Image im         = checkImage(L, 1);
  const char *name = luaL_checkstring(L, 2);

  
  FILE *pngout     = fopen( name, "wb+");
  try
  {

	//gdImagePng(im, pngout);
  }
  catch(...)
  {
	fclose(pngout);
  }
  fclose(pngout);
  return 0;
}





static int Image_gc (lua_State *L)
{
  Image im = toImage(L, 1);
  if (im) gdImageDestroy(im);
  printf("goodbye Image (%p)\n", lua_touserdata(L, 1));
  return 0;
}

static int Image_tostring (lua_State *L)
{
  lua_pushfstring(L, "Image: %p", lua_touserdata(L, 1));
  return 1;
}




static int Image_register (lua_State *L)
{
	static const luaL_reg Image_methods[] = {
  {"new",           Image_new},
  {"colorallocate", Image_color_allocate},
  {"line",          Image_line},
  {"PNG",           Image_png},
  {0,0}
};

	static const luaL_reg Image_meta[] = {
  {"__gc",       Image_gc},
  {"__tostring", Image_tostring},
  {0, 0}
};

  luaL_openlib(L, IMAGE, Image_methods, 0);  /* create methods table,
                                                add it to the globals */
  luaL_newmetatable(L, IMAGE);        /* create metatable for Image,
                                         add it to the Lua registry */
  luaL_openlib(L, 0, Image_meta, 0);  /* fill metatable */
  lua_pushliteral(L, "__index");
  lua_pushvalue(L, -3);               /* dup methods table*/
  lua_rawset(L, -3);                  /* metatable.__index = methods */
  lua_pushliteral(L, "__metatable");
  lua_pushvalue(L, -3);               /* dup methods table*/
  lua_rawset(L, -3);                  /* hide metatable:
                                         metatable.__metatable = methods */
  lua_pop(L, 1);                      /* drop metatable */
  return 1;                           /* return methods on the stack */
}
};
